﻿//-----------------------------------------------------------------------------------------------------------
// WBFSSync Project by Omega Frost 
// http://wbfssync.codeplex.com/
//
// WBFSSync is Licensed under the terms of the 
// Microsoft Reciprocal License (Ms-RL)
//-----------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WBFSe3.IO;
using System.IO;
using System.Windows.Media;
using System.ComponentModel;
using WbfsSync.Core.Operations;
using WBFSe3;
using System.Windows.Threading;
using System.Threading;

namespace WbfsSync.Core
{
    //-------------------------------------------------------------------------------------------------------
    //
    //-------------------------------------------------------------------------------------------------------
    public enum BrowserItemType
    {
        File,
        Folder,
        Game,
        Shortcut,
        Drive,
    }


    //-------------------------------------------------------------------------------------------------------
    //
    //-------------------------------------------------------------------------------------------------------
    public enum BrowserMode
    {
        Tile    = 0,
        Detail  = 1,
        Small   = 2,
        Medium  = 3,
        Large   = 4,
        Extra   = 5,
    }


    //-------------------------------------------------------------------------------------------------------
    //
    //-------------------------------------------------------------------------------------------------------
    public class BrowserItemData : INotifyPropertyChanged
    {
        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public Object obj;
        public Object meta;
        public ImageSource icon;
        public BrowserItemType type;
        public Dispatcher dispatcher;


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public event PropertyChangedEventHandler PropertyChanged;


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public ImageSource Icon
        {
            get { return this.icon; }
            set { }
        }

        public ImageSource ShortcutOverlay
        {
            get { return Extensions.GetShortcutOverlay(FrameSize); }
        }

        public int IconWidth 
        {
            get { return (int)this.icon.Width; }
            set { }
        }

        public int IconHeight
        {
            get { return (int)this.icon.Height; }
            set { }
        }

        public int FrameSize
        {
            get { return Config.IconSizes[(int)Config.BrowserMode]; }
            set { }
        }

        public bool IsSmallIcon
        {
            get
            {
                return Math.Max(this.icon.Height,
                    this.icon.Width) <
                    Config.IconSizes[(int)Config.BrowserMode];
            }
        }

        //

        public String Name
        {
            get
            {
                switch (this.type)
                {
                    case BrowserItemType.File: return (obj as FileInfo).Name;
                    case BrowserItemType.Game: return (obj as WbfsFileInfo).Name;
                    case BrowserItemType.Folder: return (obj as DirectoryInfo).Name;
                    case BrowserItemType.Shortcut: return (obj as FileSystemInfo).Name;
                    case BrowserItemType.Drive: return Core.Language.GetDriveString(obj as WbfsDriveInfo);
                    default: return String.Empty;
                }
            }

            set { }
        }

        public String Filename
        {
            get
            {
                switch (this.type)
                {
                    case BrowserItemType.File: return (obj as FileInfo).Name;
                    case BrowserItemType.Game: return (obj as WbfsFileInfo).FileNames.Files[0];
                    case BrowserItemType.Folder: return (obj as DirectoryInfo).Name;
                    case BrowserItemType.Shortcut: return (obj as FileSystemInfo).Name;
                    case BrowserItemType.Drive: return (obj as WbfsDriveInfo).Name;
                    default: return String.Empty;
                }
            }

            set { }
        }

        public String Code
        {
            get
            {
                switch (this.type)
                {
                    case BrowserItemType.Game: return (obj as WbfsFileInfo).Code;
                    default: return String.Empty;
                }
            }

            set { }
        }

        public String Group
        {
            get
            {
                switch (this.type)
                {
                    case BrowserItemType.Folder: return "File folders";
                    case BrowserItemType.Game: return "Games";
                    case BrowserItemType.Drive: return Core.Language.GetDriveGroup(this.obj as WbfsDriveInfo);
                    default: return "Files";
                }
            }

            set { }
        }

        public int GroupIdx
        {
            get
            {
                switch (this.type)
                {
                    case BrowserItemType.Folder: return 0;
                    case BrowserItemType.Game: return 1;
                    default: return 2;

                    case BrowserItemType.Drive:
                        if (!(this.obj as WbfsDriveInfo).IsCd && (this.obj as WbfsDriveInfo).IsFixed)
                            return 0;
                        else 
                            return 1;
                }
            }

            set { }
        }

        public String Type
        {
            get
            {
                switch (this.type)
                {
                    case BrowserItemType.File: 
                        String t = Extensions.GetExtensionName((this.obj as FileInfo).Extension);
                        if (t == String.Empty) return "File";
                        else return t;

                    case BrowserItemType.Folder: return "File folder";
                    case BrowserItemType.Shortcut: return "Shortcut";
                    case BrowserItemType.Game: return (this.obj as WbfsFileInfo).Format.Name;
                    case BrowserItemType.Drive: return Core.Language.GetDriveType(this.obj as WbfsDriveInfo);
                    default: return this.type.ToString();
                }
            }

            set { }
        }

        public String Region
        {
            get
            {
                switch (type)
                {
                    case BrowserItemType.Game: return (this.obj as WbfsFileInfo).Region.ToString();
                    default: return String.Empty;
                }
            }

            set { }
        }

        //

        public String Size
        {
            get
            {
                switch (type)
                {
                    case BrowserItemType.File: return Core.Language.FormatSizeEbi((this.obj as FileInfo).Length);
                    case BrowserItemType.Game: return Core.Language.FormatSizeEbi((this.obj as WbfsFileInfo).Size);
                    case BrowserItemType.Drive:

                        if (!(this.obj as WbfsDriveInfo).IsReady)
                        {
                            return String.Empty;
                        }
                        else
                        {
                            return Core.Language.FormatSizeEbi((this.obj as WbfsDriveInfo).Free)
                            + " free of " + Core.Language.FormatSizeEbi((this.obj as WbfsDriveInfo).Size);
                        }

                    default: return String.Empty;
                }
            }

            set { }
        }

        public long DriveSize
        {
            get { return (this.obj as WbfsDriveInfo).Size; }
            set { }
        }

        public long DriveUsed
        {
            get { return (this.obj as WbfsDriveInfo).Used; }
            set { }
        }

        //

        public Boolean IsGame
        {
            get { return this.type == BrowserItemType.Game; }
            set { }
        }

        public Boolean IsDrive
        {
            get { return this.type == BrowserItemType.Drive; }
            set { }
        }

        public Boolean IsDriveAndReady
        {
            get
            {
                if (this.type != BrowserItemType.Drive)
                    return false;

                return (this.obj as WbfsDriveInfo).IsReady;
            }

            set { }
        }

        public Boolean IsDriveAndLowSpace
        {
            get
            {
                if (this.type != BrowserItemType.Drive)
                    return false;

                return (this.obj as WbfsDriveInfo).Free <=
                    ((this.obj as WbfsDriveInfo).Size / 10);
            }

            set { }
        }

        public Boolean IsFolder
        {
            get { return this.type == BrowserItemType.Folder; }
            set { }
        }

        public Boolean IsShortcut
        {
            get { return this.type == BrowserItemType.Shortcut; }
            set { }
        }

        public Boolean IsShortcutDir
        {
            get
            {
                if (this.meta == null)
                    return false;

                return Directory.Exists(this.meta as String);
            }

            set { }
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public BrowserItemData(FileInfo o, Dispatcher d)
        {
            this.obj = o;
            this.dispatcher = d;
            this.type = BrowserItemType.File;
            this.icon = Extensions.GetFileIcon(o,
                Config.IconSizes[(int)Config.BrowserMode]);
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public BrowserItemData(WbfsFileInfo o, Dispatcher d)
        {
            this.obj = o;
            this.dispatcher = d;
            this.type = BrowserItemType.Game;
            this.icon = Covers.LoadCover(o.Code, 
                new OperationDelegate(CoverDownloaded));
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public BrowserItemData(DirectoryInfo o, Dispatcher d)
        {
            this.obj = o;
            this.dispatcher = d;
            this.type = BrowserItemType.Folder;
            this.icon = Extensions.GetFolderIcon(o,
                Config.IconSizes[(int)Config.BrowserMode]);
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public BrowserItemData(FileInfo fi, String path, String icon, Dispatcher d)
        {
            this.obj = fi;
            this.meta = path;
            this.dispatcher = d;
            this.type = BrowserItemType.Shortcut;
            this.icon = Extensions.ParseIcon(icon, FrameSize);
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public BrowserItemData(WbfsDriveInfo drive, Dispatcher d)
        {
            this.obj = drive;
            this.dispatcher = d;
            this.type = BrowserItemType.Drive;
            this.icon = Extensions.GetDriveIcon(drive, FrameSize);
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        private void CoverDownloaded(Operation sender, WbfsError error, int element)
        {
            if (this.Code == (sender as WebOperation).Files[element])
            {
                if (this.PropertyChanged != null)
                {
                    this.dispatcher.BeginInvoke(new ThreadStart(() =>
                        {
                            this.icon = Covers.LoadCover(this.Code, null);
                            this.PropertyChanged(this, new PropertyChangedEventArgs("Icon"));
                        }));
                }
            }
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public void Update(String property)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}
